package me.zhengjie.ppService;

import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.pojo.Response;
import me.zhengjie.pojo.sqlServer.*;
import me.zhengjie.repository.*;
import me.zhengjie.service.PPInboundMissionService;
import me.zhengjie.service.PPInfoService;
import me.zhengjie.service.PPStorageService;
import me.zhengjie.util.UniqueCodeUtil;
import me.zhengjie.wcs.PPWmsToWcs;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;


/**
 * @Author: xinglin
 * @CreateTime: 2024-08-14
 * @Description: PP入库
 * @Version: 1.0
 */

@Slf4j
@Component
@RequiredArgsConstructor
public class PPInBoundService {

    private final PPInboundMissionService ppInboundMissionService;
    private final PPInboundMissionRepository ppInboundMissionRepository;
    private final PPInboundMissionHistoryRepository ppInboundMissionHistoryRepository;
    private final PPWmsToWcs wmsToWcs;
    private final PPStorageService ppStorageService;
    private final PPStationRepository ppStationRepository;
    private final EntranceTcpService entranceTcpService;
    private final PpPalletRepository ppPalletRepository;
    private final PPInfoRepository ppInfoRepository;
    private final PPTaskResultRepository ppTaskResultRepository;


    private static final Logger ppLog = LoggerFactory.getLogger("pp");


    /**
     * 生成入库任务
     */
    @Transactional(rollbackFor = Exception.class)
    public void createInboundMission(String palletCode, String stationCode) {

        try {
            //查看是否有对应的载盘入库任务
            if (ppInboundMissionRepository.findPPInboundMissionByPalletCode(palletCode) != null) {
                log.error(palletCode+"该载盘已存在入库任务，请勿重复生成入库任务");
                throw new Exception("该载盘已存在入库任务，请勿重复生成入库任务");
            }

            if (ppTaskResultRepository.findPPTaskResultBylpnCode(palletCode) != null) {
                log.error(palletCode+"该载盘任务TaskResult中存在，请联系管理员进行处理");
                throw new Exception("该载盘任务TaskResult中存在，请联系管理员进行处理");
            }


            // 创建PPInboundMission对象
            PPInboundMission ppInboundMission = new PPInboundMission();
            // 设置任务编码
            ppInboundMission.setMissionCode(UniqueCodeUtil.createCode());
            // 设置托盘编码
            ppInboundMission.setPalletCode(palletCode);
            // 设置任务状态为已分配任务
            ppInboundMission.setMissionStatus(1);
            // 设置优先级
            ppInboundMission.setPriority(0);
            // 设置创建时间
            ppInboundMission.setCreateTime(LocalDateTime.now());

            //设置入库口和分配储位
            ppInboundMission.setSource(stationCode);
            List<PPStorage> storages = distributeStorage();
            PPStorage storage = storages.get(0);

            // 设置入库任务的目的地为仓库编码
            ppInboundMission.setDestination(storage.getStorageCode());
            // 设置入库任务的创建时间为当前时间
            ppInboundMission.setCreateTime(LocalDateTime.now());

            //通过
            PpPallet ppPallet =  ppPalletRepository.findByPalletCode(palletCode);

            if (ObjectUtil.isNotEmpty(ppPallet.getPpBatch())) {
                PPInfo ppInfo = ppInfoRepository.getPPInfoByPpBatch(ppPallet.getPpBatch());
                ppInboundMission.setPpId(ppInfo.getId());
                ppInboundMission.setPpQty(ppInfo.getPpQty());
            }

            ppInboundMissionRepository.save(ppInboundMission);

            // 更新储位信息,锁库存
            ppStorageService.lockStorage(storage.getStorageCode());

        } catch (Exception e) {
            ppLog.error("生成入库任务失败,失败原因", e.toString());

        }
    }


    /**
     * 分配储位, 需要根据库区分配
     *
     * @return 分配到的储位
     */
    private List<PPStorage> distributeStorage() {
        return ppStorageService.findSuitableStorage();

    }


    /**
     * 生成发送到wcs的入库任务
     *
     * @param inBoundMission wms管理的入库任务
     * @return wcs管理的入库任务
     */
    public PPWmsTask getPPWmsTask(PPInboundMission inBoundMission) {
        // 创建一个新的PPWmsTask对象
        PPWmsTask wmsTask = new PPWmsTask();
        wmsTask.setLogicalAddressType(1);
        wmsTask.setWmsTaskId(inBoundMission.getMissionCode());
        wmsTask.setLpnCode(inBoundMission.getPalletCode());
        wmsTask.setLpnType(1);
        wmsTask.setWcsTaskType(1);
        wmsTask.setAisle(1);
        wmsTask.setFromLocation(inBoundMission.getSource());
        wmsTask.setToLocation(inBoundMission.getDestination());
        wmsTask.setLevel(inBoundMission.getPriority());
        wmsTask.setStatus(inBoundMission.getMissionStatus());
        wmsTask.setCreated(inBoundMission.getCreateTime());
        return wmsTask;
    }


    @Transactional
    public Response sendInBoundTask(PPInboundMission PPInBoundMission) {

        //获取PPWmsTask对象
        PPWmsTask ppWmsTask = getPPWmsTask(PPInBoundMission);
        //更新任务状态
        updateAfterSendTask(ppWmsTask);
        //调用wmsToWcs接口发送任务
        return wmsToWcs.sendTask(ppWmsTask);

    }


    public PPInboundMission findNewInBoundMission() {
        if (ppInboundMissionRepository.findNewPPInboundMission().size() > 0) {
            return ppInboundMissionRepository.findNewPPInboundMission().get(0);
        }else {
            return null;
        }

    }


    @Transactional(rollbackFor = Exception.class)
    public void updateAfterSendTask(PPWmsTask wmsTask) {
        ppInboundMissionRepository.updateStatusByMissionCode(String.valueOf(wmsTask.getWmsTaskId()), 2);
    }


    @Transactional(rollbackFor = Exception.class)
    public void deletePPInboundMissionById(Integer id) {
        ppInboundMissionRepository.deleteById(id);
    }


    //发送启动回流信的信号到plc，让载盘流向入库口
    public void sendAllowInBoundPlc(String stationCode) {

        PPStation ppStation = ppStationRepository.getByStationCode(stationCode);
        //isAllow=1是写入允许入库，taskResult.getToLocation()是出库口，type=1表示类型为入库
        entranceTcpService.writeRequestResponseType(1, ppStation.getStationName(), 1);

    }

    //当发送任务失败的时候一键重置功能，便于测试
    public void resetInboundTask() {


    }

    public boolean ifExistPallet(String palletCode) {
        PPInboundMission inBoundMission = ppInboundMissionRepository.findPPInboundMissionByPalletCode(palletCode);
        return !ObjectUtil.isEmpty(inBoundMission);
    }


}
